package com.example.springboot.aop.aspect;

import com.example.springboot.aop.annotation.SystemControllerLog;
import com.example.springboot.aop.dao.SystemLogMapper;
import com.example.springboot.aop.entity.SystemLogModel;
import com.example.springboot.aop.service.SystemLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 切点类
 */
@Aspect
@Component
public class SystemLogAspect {

	// 本地异常日志记录对象
	private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

	@Autowired
	private SystemLogMapper systemLogMapper;
	@Autowired
	public SystemLogService logService;


	// Controller层切点,针对在业务模块标注SystemControllerLog注解记录日志
	@Pointcut("@annotation( com.example.springboot.aop.annotation.SystemControllerLog )")
	public void controllerAspect() {
	}

	/**
	 * 前置通知 用于拦截Controller层记录用户的操作
	 *
	 * @param joinPoint 切点
	 */
	@Before("controllerAspect()")
	public void doBefore(JoinPoint joinPoint) {
		try {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			// 请求的IP
			String logIP = request.getHeader("X-Real-IP");
			if (StringUtils.isEmpty(logIP)) {
				logIP = request.getRemoteAddr();
			}

			SystemLogModel slm = getControllerMethodDescription(joinPoint);
			logService.logService(slm.getModuleID(), slm.getLogAction(), slm.getLogContent(), request);
		} catch (Exception e) {
			// 记录本地异常日志
			logger.error("==前置通知异常==");
			logger.error("异常信息:{}", e.getMessage());
		}
	}

	/**
	 * 获取注解中对方法的描述信息 用于Controller层注解
	 *
	 * @param joinPoint 切点
	 * @return 方法描述
	 * @throws Exception
	 */
	public static SystemLogModel getControllerMethodDescription(
			JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class targetClass = Class.forName(targetName);
		Method[] methods = targetClass.getMethods();
		String description = "";
		SystemControllerLog log;
		SystemLogModel logM = new SystemLogModel();
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				Class[] clazzs = method.getParameterTypes();
				if (clazzs.length == arguments.length) {
					log = method.getAnnotation(SystemControllerLog.class);
					logM.setModuleID(log.ModuleID());
					logM.setLogAction(log.LogAction());
					logM.setLogContent(log.LogContent());
					break;
				}
			}
		}
		return logM;
	}
}